package glemipsc;

import java.util.Iterator;
import java.util.List;

import glemipsc.implementations.Argument;
import glemipsc.implementations.Implementation;
import glemipsc.implementations.Instruction;

public class TypeArray extends Type {
	public TypeArray(Type nested) {
		typeFormat = Type.TypeFormat.ARRAY;
		this.setNestedType(nested);
	}

	public TypeArray(Type nested, int length) {
		typeFormat = Type.TypeFormat.ARRAY;
		this.setNestedType(nested);
		this.length = length;
	}

	public String getName() {
		return this.nestedType.getName() + "*";
	}
	
	public boolean isCompatibleWith(Type type) {
		if (type.typeFormat == Type.TypeFormat.INTEGER)
			return true;
		if (type.typeFormat != this.typeFormat)
			return false;
		return this.nestedType.isCompatibleWith(type.nestedType);
	}

	public int getValueLength() {
		return GLEMipsC.compiler.environment.implementation.getPointerSize() / 8;
	}
	
	public int sizeOf() {
		if (length == 0)
			return getValueLength();
		return length * nestedType.sizeOf();
	}
	
	public boolean equals(Object o) {
		if (!super.equals(o))
			return false;
		return nestedType.equals(((TypeArray)o).nestedType);
	}

	public String toString() {
		return this.length == 0 ? this.nestedType.toString() + "*" : this.nestedType.toString() + "[" + length + "]";
	}
	
	public boolean computeInitialization(Address el, Object value, List<Instruction> instructions) {
		Implementation impl = GLEMipsC.compiler.getEnvironment().implementation;
		
		boolean result = true;
		
		if (value instanceof List) {
			List val = (List) value;
			if (this.length != 0 && this.length < val.size())
				return false;
			if (this.length == 0)
				return false;
			int i = 0;
			for (Iterator iter = val.iterator(); iter.hasNext() && result; i++) {
				value = iter.next();
				Address newAddress = new TranslatedAddress(el, el.getSegment(), i * nestedType.sizeOf() / 4);
				result = result && nestedType.computeInitialization(newAddress, value, instructions);
			}
		}
		else if (value instanceof ConstantString) {
			String val = ((ConstantString) value).toString();
			if (this.length != 0 && this.length < val.length() + 1)
				return false;
			if (this.length == 0)
				// TODO: Impostare il puntatore ai dati
				return true;
			int i;
			for (i = 0; i < val.length() && result; i++) {
				Address newAddress = new TranslatedAddress(el, el.getSegment(), i * nestedType.sizeOf() / 4);
				result = result && nestedType.computeInitialization(newAddress, new ConstantChar(val.substring(i, i+1)), instructions);
			}
			Address newAddress = new TranslatedAddress(el, el.getSegment(), i * nestedType.sizeOf() / 4);
			result = result && nestedType.computeInitialization(newAddress, new ConstantChar("\0"), instructions);
		}
		else
			return false;
		
		return result;
	}
}
